<?php

namespace app\install\controller;

use app\BaseController;
use app\install\core\InstallCore;
use think\facade\Cache;
use think\facade\Db;

class Index extends BaseController
{
    protected $layout = 'default';
    /**
     * 首页
     * @return \think\response\View
     */
    public function index()
    {
        $this->view->assign('step', url('step1'));
        return $this->view->fetch();
    }
    public function step1()
    {
        //系统变量
        $system_variables = [];
        $phpv = PHP_VERSION;
        $os = PHP_OS;
        $server = $_SERVER[ 'SERVER_SOFTWARE' ];

        $host = ( empty($_SERVER[ 'REMOTE_ADDR' ]) ? $_SERVER[ 'REMOTE_HOST' ] : $_SERVER[ 'REMOTE_ADDR' ] );
        $name = $_SERVER[ 'SERVER_NAME' ];

        $verison = !( version_compare(PHP_VERSION, '8.0.0') == -1 );
        //pdo
        $pdo = extension_loaded('pdo') && extension_loaded('pdo_mysql');
        $system_variables[] = [ "name" => "pdo", "need" => "开启", "status" => $pdo ];
        //curl
        $curl = extension_loaded('curl') && function_exists('curl_init');
        $system_variables[] = [ "name" => "curl", "need" => "开启", "status" => $curl ];
        //openssl
        $openssl = extension_loaded('openssl');
        $system_variables[] = [ "name" => "openssl", "need" => "开启", "status" => $openssl ];
        //gd
        $gd = extension_loaded('gd');
        $system_variables[] = [ "name" => "GD库", "need" => "开启", "status" => $gd ];
        //fileinfo
        $fileinfo = extension_loaded('fileinfo');
        $system_variables[] = [ "name" => "fileinfo", "need" => "开启", "status" => $fileinfo ];
        //sodium
        $sodium = extension_loaded('sodium');
        $system_variables[] = [ "name" => "sodium", "need" => "开启", "status" => $sodium ];

        $root_path = str_replace("\\", DIRECTORY_SEPARATOR, dirname(__FILE__, 4));
        $root_path = str_replace("../", DIRECTORY_SEPARATOR, $root_path);
//        echo '<pre>';
//        print_r($root_path);
//        exit;
        $dirs_list = [
            [
                "path" => $root_path.DIRECTORY_SEPARATOR.'addons' . DIRECTORY_SEPARATOR,
                "path_name" => "/addons",
                "name" => "插件目录",
                "create"=>true
            ],
//            [
//                "path" => $root_path . DIRECTORY_SEPARATOR . ".env",
//                "path_name" => ".env",
//                "name" => "env",
//                "create"=>false
//            ],
            [
                "path" => $root_path . DIRECTORY_SEPARATOR . ".env.example",
                "path_name" => ".env.example",
                "name" => "env",
                "create"=>true
            ],
            [
                "path" => $root_path . DIRECTORY_SEPARATOR . 'runtime' . DIRECTORY_SEPARATOR,
                "path_name" => "/runtime",
                "name" => "runtime",
                "create"=>true
            ],
            [
                "path" => $root_path . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR,
                "path_name" => "/public/uploads",
                "name" => "upload",
                "create"=>true
            ],
            [
                "path" => $root_path . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'addons' . DIRECTORY_SEPARATOR,
                "path_name" => "/public/addons",
                "name" => "插件静态文件目录",
                "create"=>true
            ],
//            [ "path" => $root_path . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR, "path_name" => "/app/install", "name" => "安装目录" ]
        ];
        //目录 可读 可写检测
        $is_dir = true;
        foreach ($dirs_list as $k => $v) {
            if($v[ 'create']){
                if($v['path'][ strlen($v['path']) - 1]==DIRECTORY_SEPARATOR){
                    if(!is_dir($v[ "path" ])){
                        @mkdir($v[ "path" ], 0755, true);
                    }else{
                        @chmod($v[ "path" ], 0755);
                    }

                }else{
                    $path_array = explode(DIRECTORY_SEPARATOR, $v[ "path" ]);
                    $tem_file_name = array_pop($path_array);
                    $tem_path = implode(DIRECTORY_SEPARATOR, $path_array);
                    if(is_dir($tem_path)){
                        @chmod($tem_path, 0755);
                    }else{
                        @mkdir($tem_path, 0755, true);
                    }
                    if(!is_file($v[ "path" ])){
                        file_put_contents($v[ "path" ], "");
                        @chmod($v[ "path" ], 0755);
                    }else{
                        @chmod($v[ "path" ], 0755);
                    }

                }
            }

            $is_readable = is_readable($v[ "path" ]);
            $is_write = is_write($v[ "path" ]);
            $dirs_list[ $k ][ "is_readable" ] = $is_readable;
            $dirs_list[ $k ][ "is_write" ] = $is_write;
            if (!$is_readable || !$is_write) {
                $is_dir = false;
            }
        }
        $this->assign("root_path", $root_path);
        $this->assign("system_variables", $system_variables);
        $this->assign("phpv", $phpv);
        $this->assign("server", $server);
        $this->assign("host", $host);
        $this->assign("os", $os);
        $this->assign("name", $name);
        $this->assign("verison", $verison);
        $this->assign("dirs_list", $dirs_list);
        if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir) {
            $continue = true;
        } else {
            $continue = false;
        }
        $this->assign("continue", $continue);
        $this->view->assign('step',url('step2'));
        $this->view->assign('stup',url('index'));
        return $this->view->fetch();
    }
    public function step2()
    {
        $this->view->assign('step',url('step3'));
        $this->view->assign('stup',url('step1'));
        $this->view->assign('testdb',url('testdb'));
        $this->view->assign('getInstallInfo',url('getInstallInfo'));
        $this->view->assign('install',url('install'));
        $this->view->assign('initData',url('initData'));
        $this->view->assign('installSuccess',url('installSuccess'));
        $this->view->assign('root_url',$this->request->domain());
        return $this->view->fetch();
    }
    public function testdb()
    {
        $res = InstallCore::testdbHand();
        if($res['code']==0){
            return error($res['msg']);
        }
        return success($res['msg'],$res['data']);
//        return $this->success($res['msg'],'',$res['data']);
    }
    public function install()
    {
//        $data = $this->request->param();
        set_time_limit(0);
        Cache::delete('install_data');
        Cache::set('install_status', 0);//进行中
        $check = InstallCore::testdbHand();
        if($check['code']==0){
            $this->setSuccessLog([ $check['msg'], 'error' ]);
            return $this->error($check['msg']);
        }
        $admin_name = $this->request->param('admin_name', "");
        $username = $this->request->param('username', "");
        $password = $this->request->param('password', "");
        $password2 = $this->request->param('password2', "");
        $dbhost = $this->request->param('dbhost', "");
        $dbport = $this->request->param('dbport', "3306");
        $dbuser = $this->request->param('dbuser', "");
        $dbpwd = $this->request->param('dbpwd', "");
        $dbname = $this->request->param('dbname', "");
        $dbprefix = $this->request->param('dbprefix', "");

        if(empty($dbhost)||empty($dbuser)||empty($dbpwd)||empty($dbname)){
            $this->setSuccessLog([ '数据库信息不能为空', 'error' ]);
            return $this->error(msg:'数据库信息不全');
        }

//        $site_name = $this->request->param('site_name', "");
//        $site_username = $this->request->param('site_username', "");
//        $site_password = $this->request->param('site_password', "");
//        $site_password2 = $this->request->param('site_password2', "");

        if ($admin_name == '' || $username == '' || $password == '') {
            $this->setSuccessLog([ '平台信息不能为空', 'error' ]);
            return $this->error(msg:'平台信息不能为空!');
        }


        if ($password != $password2) {
            $this->setSuccessLog([ '平台两次密码输入不一样，请重新输入', 'error' ]);
            return $this->error(msg:'平台两次密码输入不一样，请重新输入');
        }
//        APP_DEBUG = true
//
//DB_TYPE = mysql
//DB_HOST = 127.0.0.1
//DB_NAME = test
//DB_USER = username
//DB_PASS = password
//DB_PORT = 3306
//DB_CHARSET = utf8
//
//DEFAULT_LANG = zh-cn
        $envs = [
            "APP_DEBUG"=>"true",
            "DB_HOST"=>$dbhost,
            "DB_NAME"=>$dbname,
            "DB_USER"=>$dbuser,
            "DB_PASS"=>$dbpwd,
            "DB_PORT"=>$dbport,
            "DB_CHARSET"=>"utf8",
            "DEFAULT_LANG"=>"zh-cn",
            "DB_PREFIX"=>$dbprefix,
            "APP_CACHE_PREFIX"=>"prefix_".uniqid()
        ];
        $env_dir = root_path() . DIRECTORY_SEPARATOR . ".env";
        $env_str = "";
        foreach ($envs as $key => $value){
            $env_str .= $key . " = " . $value . PHP_EOL;
        }
//        try {
        $res = file_put_contents($env_dir, $env_str);
        if(!$res){
            $this->setSuccessLog([ '配置文件写入失败', 'error' ]);
            return error(msg:'配置文件写入失败');
        }
        $sqlFile = root_path() . DIRECTORY_SEPARATOR . "install.sql";
        if (!is_file($sqlFile)) {
            $this->setSuccessLog([ '安装文件不存在', 'error' ]);
            return error(msg:'安装文件不存在');
        }
        //数据库
        //数据库连接测试
        $conn = @mysqli_connect($dbhost, $dbuser, $dbpwd, "", $dbport);
        if (!$conn) {
            return error('连接数据库失败！请检查连接参数!');
        }
        //数据库可写和是否存在测试
        try {
            $empty_db = @mysqli_select_db($conn, $dbname);
        }catch (\Exception $e){
            $empty_db = false;
        }
        if ($empty_db) {
            $sql = "DROP DATABASE `$dbname`";
            $retval = mysqli_query($conn, $sql);
            if (!$retval) {
                return error('删除数据库失败: ' . mysqli_error($conn));
            }
        }
        //如果数据库不存在，我们就进行创建。
        $dbsql = "CREATE DATABASE `$dbname`";
        $db_create = mysqli_query($conn, $dbsql);
        if (!$db_create) {
            return error('创建数据库失败，请确认是否有足够的权限!');
        }
        //链接数据库
        @mysqli_select_db($conn, $dbname);

        //导入SQL并执行。
        $get_sql_data = file_get_contents($sqlFile);
        $get_sql_data = str_replace("__PREFIX__", $dbprefix, $get_sql_data);
        $sql_query = $this->getSqlQuery($get_sql_data);
        @mysqli_query($conn, "SET NAMES utf8mb4");
        $query_count = count($sql_query);

        for ($i = 0; $i < $query_count; $i++) {
            $sql = trim($sql_query[ $i ]);
            $is_write = false;
            if (str_contains($sql, 'CREATE TABLE')) {
                $match_item = preg_match('/CREATE TABLE [`]?(\\w+)[`]?/is', $sql, $match_data);
                $is_write = true;
            } elseif (str_contains($sql, 'ALTER TABLE')) {
                $match_item = preg_match('/ALTER TABLE [`]?(\\w+)[`]?/is', $sql, $match_data);

            } elseif (str_contains($sql, 'INSERT INTO')) {
                $match_item = preg_match('/INSERT INTO [`]?(\\w+)[`]?/is', $sql, $match_data);
            } else {
                $match_item = 0;
            }
            if ($match_item > 0) {
                try {
                    $table_name = $match_data[ 1 ];
                    $new_table_name = $table_name;
                    $sql_item = $this->str_replace_first($table_name, $new_table_name, $sql);
                    @mysqli_query($conn, $sql_item);
                    if ($is_write) $this->setSuccessLog([ '创建表' . $table_name, 'success' ]);
                } catch (\Exception $e) {
                    $this->setSuccessLog([ $e->getMessage(), 'error' ]);
                    return error('数据库解析失败2' . $e->getMessage());
                }
            }
        }
        @mysqli_close($conn);

        Cache::set('install_status', 1);//成功
        return $this->success("安装成功",['status'=>1]);
    }
    public function getInstallInfo()
    {
        return $this->success("获取成功");
    }
    public function str_replace_first($search, $replace, $subject)
    {
        return implode($replace, explode($search, $subject, 2));
    }
    public function getSqlQuery($sql_data)
    {
//        $this->checkLock();
        $sql_data = preg_replace("/TYPE=(InnoDB|MyISAM|MEMORY)( DEFAULT CHARSET=[^; ]+)?/", "ENGINE=\\1 DEFAULT CHARSET=utf8", $sql_data);

        $sql_data = str_replace("\r", "\n", $sql_data);
        $sql_query = [];
        $num = 0;
        $sql_arr = explode(";\n", trim($sql_data));
        unset($sql);
        foreach ($sql_arr as $sql) {
            $sql_query[ $num ] = '';
            $sqls = explode("\n", trim($sql));
            $sqls = array_filter($sqls);
            foreach ($sqls as $query) {
                $str1 = $query[ 0 ] ?? '';
                if ($str1 != '#' && $str1 != '-')
                    $sql_query[ $num ] .= $query;
            }
            $num++;
        }
        return $sql_query;
    }
    protected function setSuccessLog($data)
    {
        if ($data[ 1 ] == 'error') {
            Cache::set('install_status', -1);
        }
        $time = @(int) microtime(true);
        $data[] = date('Y-m-d H:i:s', $time);
        $install_data = Cache::get('install_data') ?? [];
        $install_data[] = $data;
        Cache::set('install_data', $install_data);
    }
    public function initData()
    {
//        $this->checkLock();
        $admin_name = $this->request->param('admin_name', "");
        $username = $this->request->param('username', "");
        $password = $this->request->param('password', "");
        $password2 = $this->request->param('password2', "");
        if ($admin_name == '' || $username == '' || $password == '') {
            return $this->error('平台信息不能为空!');
        }

        if ($password != $password2) {
            return $this->error('平台两次密码输入不一样，请重新输入');
        }
        $fileName = root_path().'config/install.lock';
        file_put_contents($fileName, 'install');
        //获取默认套餐
        $salt = unique_random(5);
        $admin_log = [
            'username'=>$username,
            'nickname'=>ucfirst($username),
            'password'=>create_password($password,$salt),
            'salt'=>$salt
        ];
        Db::name('admin')->where('id',1)->update($admin_log);
        $admin_log['id'] = 1;
        $url = url('installSuccess');
        return $this->success('初始化成功',['url'=>$url]);
    }
    public function installSuccess()
    {
        $model = get_app_map('admin');
        $url = "/{$model}/index/index";
        $this->view->assign('url',$url);
        return $this->view->fetch();
    }
}